查看原文
其他

【第1224期】追根溯源:箭头函数的前世今生

肖蜀黍 前端早读课 2019-07-26

前言

又快到月末了,周末就看看“故事”吧,今日早读文章由@肖蜀黍投稿分享。

@肖蜀黍,曾服务于众安、腾讯,现为自由职业的全栈工程师,长期维护《趣你的大前端》知乎专栏。

正文从这开始~

Arrow Function(箭头函数),es6的新特性之一,你可能已经熟练使用并且爱上了它。但这个看似普通的语法糖,有着一个漫长而精彩的故事,本文将带你回到一百多年前,看看它是怎么走进我们世界的。

史前:第三次数学危机

在很久很久以前,人们很傻很天真,相信一切数字都可以表达为整数之比。直到公元前400年,毕达哥拉斯发现了无理数,引发第一次数学危机。

17世纪的晚期,无穷小的问题带来了第二次数学危机,幸运的是出来两位伟人:牛顿和莱布尼兹,用微积分的方式匡扶了即将倒下的数学大厦。

风平浪静不过两百年,又出来一个搞事情的家伙,叫做罗素(Bertrand Russell)。他提出一个问题,瞬间让数学家们炸锅了,史称第三次数学危机。

这个问题叫做理发师悖论,通俗的描述是这样的:

理发师的规矩是:只为不给自己理发的人理发。那么问题就来了,他应不应该给自己理发?

  • 如果不应该,那他就属于不给自己理发的人,但按照规矩,他有应该给自己理发。

  • 如果应该,那他就属于给自己理发的人,但按照规矩,他就不能给自己理发。

此悖论也可以用数学公式来描述:

如果有一个集合,它包含任何非己的元素,那么这个集合是否属于它本身呢?

惶恐:可计算性问题

危机产生后,人类再次陷入了深深的沉思:还有哪些问题是无法证明的?计算或者推理的边界在哪?怎么判定一个问题是否可解?如果无解,那原因又是什么?

要解除这个危机,首先必须定义可计算这一概念。20世纪30年代,搞数学的各路英雄好汉,纷纷加入了可计算性问题的研究。

丘奇通过建模的方式,很快找到一个神器,并命名曰:λ演算(lambda calculus)。λ演算是一种表达式,它由引入变量、参数、函数声明、函数应用组成。

与此同时,图灵(丘奇的学生,也是人工智能的爸爸)发明了图灵机。图灵机是一台假想的机器,能模拟人们用纸笔进行数学运算的过程。至此,邱奇-图灵论题已经成功的解决了在可计算理论中的判定性问题。

有了图灵机的灵感,冯·诺伊曼提出一个体系,抽象出输入设备、控制器、运算器、存储器、输出器等概念。并在此理论上,美国人制造了第一台计算机—埃尼阿克(ENIAC:Electronic Numerical Integrator And Computer)

神器:λ演算

究竟 λ演算是什么鬼,竟然能间接引发人类的科技革命?因为λ演算研究的是函数的本质性问题,所以形式极其简单:

上面的E称为λ-表达式(expressions)或λ-terms,它的值有三种形式:

  • 变量(variables)。

  • 函数声明或抽象(function creation/abstraction)。需要注意是的,函数中有且仅有一个参数。在λx. E中,x是参数,E是函数体。

  • 函数应用(function application)。也就是我们理解的函数调用,但官方术语就叫函数应用。

等一等, λ演算中函数只有一个参数?那两个或者以上参数的函数,岂不是没法玩了?这样的λ演算,也未免太弱了吧?

非也,这正是λ的神奇之处!如果你想有多个参数,很简单,使用currying技术即可:

λx y.(+ x y)---->λx.(λ y.+ x y)

玩法是这样的:你调用了一个函数,这个函数返回另一个函数,返回的函数中存储保留了调用函数的变量。

似曾相识对不对,没错,currying就是闭包的鼻祖。

或者你也可以用Python的来实现:

def add(x):
returnlambda y
: x+y
add
(4)(3)//return 7

此外,还有更多玩法,比如用 λ演算来定义变量、数值、键值对……

//定义Boolean类型
truexy. x
falsexy. y
if E1 then E2 else E3 = E1 E2 E3

开拓:Lisp语言

公元1958年,受邱奇的λ演算的影响,出现了LISP编程语言。它有独特和完全括号的前缀符号表示法。它是现今第二悠久而仍广泛使用的高级编程语言。只有FORTRAN编程语言比它更早一年。

LISP 编程语族已经演变出许多种方言。现代最著名的通用编程语种是 Common LISP 和 Scheme。

再后来故事,我们就熟悉了,1994年JavaScript诞生了,它是一个超级大杂烩,看看它的这些干爹:

  1. 借鉴C语言的基本语法;

  2. 借鉴Java语言的数据类型和内存管理;

  3. 借鉴Scheme语言,将函数提升到”第一等公民”的地位;

  4. 借鉴Self语言,使用基于原型(prototype)的继承机制。

未来:函数式编程

最后,千呼万唤,屎都出来了。2015年,终于迎来了我们的主角:箭头函数

(param1, param2,…, paramN)=>{ statements }
(param1, param2,…, paramN)=> expression
// 等同于:  => { return expression; }
// 如果只有一个参数,圆括号是可选的:
(singleParam)=>{ statements }
singleParam
=>{ statements }
// 无参数的函数需要使用圆括号:
()=>{ statements }

此外,由于Node的迅猛发展,以及React/Vue/Angular这些洪水猛兽,前端们喊出里一个新的口号:函数式编程

这又是一个巨大的话题,会不会再次掀起腥风血雨?

最后,为你推荐

【第729期】什么时候不该使用es6箭头函数

【第1038期】ES6的工厂函数

关于本文
作者:@肖蜀黍
原文:https://mp.weixin.qq.com/s/52wN6rPvbN5K_Cp0OkEHBQ

【活动】3月31日,中国第四届CSS大会相约厦门

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存